package magicboard.model
{
  import flash.display.Graphics;
  import flash.geom.Point;
  
  import magicboard.geometry.Rect;
  import magicboard.geometry.Vector;
  import magicboard.geometry.algorithms.DPPolylineSimplification;
  
  import mx.utils.StringUtil;
  
	
	/**
	 * Curve considit of sets of points 
	 */
	public class InkStroke
	{
	  // --------------------------------------------------------------------------------------------
		public function InkStroke(ps:Array = null){
			
			_type = "undefined";
			if(ps != null){
		  	_points = ps;
		 	}else{
				_points = new Array();
		 	}
		}
		
	  // --------------------------------------------------------------------------------------------
		public function addPoint(p:Point):void{
		  points.push(p);
		}

	  // --------------------------------------------------------------------------------------------
		public function get boundingBox():Rect {
			
			if(_box == null){
				for each( var point:Point in points){
					if(_box == null){
						_box = new Rect(point.x, point.y);
					}
					else{
						if(point.x < _box.left)
							_box.left = point.x;
						else if(point.x > _box.right)
							_box.right = point.x;
	
						if(point.y < _box.top)
							_box.top = point.y;
						else if(point.y > _box.bottom)
							_box.bottom = point.y;
					}
				}
			}
			
			return _box;	
		}

	  // --------------------------------------------------------------------------------------------
		public function draw(g:Graphics):void{

			if(points.length > 0){
	    	g.moveTo(points[0].x, points[0].y);
	    	for(var i:int = 1; i < points.length; i++) {
	    		g.lineTo(points[i].x, points[i].y);
	    	}
	  	}
		}
		
	  // --------------------------------------------------------------------------------------------
	  /**
	  * Length can be precalculated
	  */
		public function get length():Number{
		
			if(_length < 0){
	      var v:Vector;
	
				_length = 0;
	    	for(var i:int = 1; i < points.length; i++) {
	    	  v = Vector.points2Vector(points[i], points[i-1]);
	    		_length += v.length;
	    	}
			}
			
			return _length;
		}
		
		// --------------------------------------------------------------------------------------------
		/**
		 * @return true if there are any points.
		 */
		public function loadFromString(data:String):Boolean{
			var map:Array = data.split(":");
			var formatCorrect:Boolean = false;
			
			if(map.length == 2){
				_type = StringUtil.trim(map[0]);
				var points:Array = map[1].match(/[\d\.]+/g);
			
      	for(var i:int = 1; i < points.length; i += 2){
      		addPoint(new Point(points[i-1], points[i]));
      		formatCorrect = true;
      	}
   		}
   		
   		return formatCorrect;
		}
		
		
	  // --------------------------------------------------------------------------------------------
		public function get points():Array {
			return _points;
		}
		
	  // --------------------------------------------------------------------------------------------
		public function saveToString():String{
			var text:String = _type + ": ";
			
			for(var i:int = 0; i < _points.length; i++){
				text += "(" + _points[i].x + "," + _points[i].y + ")";
				if( i < _points.length-1)
					text += ", "; 
			}
			
			return text;
		}

	  // --------------------------------------------------------------------------------------------
	  /** Get points after segmentation */
		public function get simplifiedPoints():Array {
			
			if(_simplifiedPoints == null){
				
				var dp:DPPolylineSimplification = new DPPolylineSimplification();
				_simplifiedPoints = new Array();
				
				dp.tolerance = 0.1 * boundingBox.diagonalLength;
				_simplifiedPoints = dp.simplify(points);
			}
			
			return _simplifiedPoints;
		}
		
	  // --------------------------------------------------------------------------------------------
		public function toString():String{
		  return _type + " with " + (points.length-1) + " vectors.";
		}

	  // --------------------------------------------------------------------------------------------
		public function get type():String {
			return _type;	
		}

	  // --------------------------------------------------------------------------------------------
		public function set type(t:String):void {
			_type = t;	
		}

		
 	  // --------------------------------------------------------------------------------------------
    // Private members
    private var _points:Array;
    private var _simplifiedPoints:Array = null;
    private var _type:String;
    private var _length:Number = -1;
    private var _box:Rect;		
	}
}